/**
 * 发布订阅 是一种对象间 一对多的依赖关系，当一个对象的状态发生改变时，所有依赖于它的对象都将得到通知。
 * 发布订阅模式定义了一种一对多的关系，让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时，会通知所有观察者对象，使它们能够自动更新自己。
 * 发布订阅模式是一种对象间一对多的关系，通过引入调度中心来降低对象间的耦合性，当一个对象改变状态时，所有依赖于它的对象都会收到通知并自动更新。
 */
// class Event {
//   constructor() {
//     this.message = {};
//   }
//   // 订阅事件
//   $on(type, fn) {
//     if (!this.message[type]) {
//       this.message[type] = [];
//     }
//     this.message[type].push(fn);
//   }
//   // 取消订阅事件
//   $off(type, fn) {
//     if (!type) return;
//     if (!fn) {
//       this.message[type] = [];
//       return;
//     }
//     this.message[type] = this.message[type].filter((item) => item !== fn);
//   }
//   // 发布事件
//   $emit(type) {
//     if (!this.message[type]) return;
//     this.message[type].forEach((item) => {
//       item();
//     });
//   }
// }
// let p1 = new Event();
// p1.$on("a", handleA);
// p1.$on("a", handleB);
// // p1.$off('a');
// // p1.$off('a', handleA);
// p1.$emit("a");
// function handleA() {
//   console.log("handleA");
// }
// function handleB() {
//   console.log("handleB");
// }
// console.log("p1", p1);
function mitt() {
  const all = new Map();

  const on = (type, handler) => {
    const handlers = all.get(type);
    if (handlers) {
      handlers.push(handler);
    } else {
      all.set(type, [handler]);
    }
  };

  const off = (type, handler) => {
    const handlers = all.get(type);
    if (!handlers) {
      return;
    }

    if (handler) {
      const handlerIndex = handlers.indexOf(handler);
      const hasHandler = handlerIndex !== -1;
      if (hasHandler) {
        handlers.splice(handlerIndex, 1);
      }
    } else {
      all.set(type, []);
    }
  };

  const emit = (type, params) => {
    let handlers = all.get(type);
    if (handlers) {
      handlers.slice().map((handler) => handler(params));
    }

    // 没有查找到监听事件，判断是否监听了所有事件 *
    handlers = all.get('*');
    if (handlers) {
      handlers.slice().map((handler) => handler(params));
    }
  };

  const once = (type, handler) => {
    const onceFn = (params) => {
      handler(params);
      off(type, onceFn);
    };

    on(type, onceFn);
  };

  // 清除所有订阅则使用 Map 自身的 clear 函数

  return {
    all,
    on,
    once,
    off,
    emit,
  };
}
const emitter = mitt();

// 订阅事件
emitter.on('foo', (e) => console.log('foo', e));
emitter.on('fxx', (e) => console.log('fxx', e));

console.log(
  '%c [  ]-113',
  'font-size:13px; background:pink; color:#bf2c9f;',
  emitter
);

// 订阅所有的事件
emitter.on('*', (type, e) => console.log('xx', type, e));

// 发布事件
emitter.emit('foo', { a: 'b' });
// emitter.emit("foo", { a: "b" });

// 清空所有事件
// emitter.all.clear();

// function onFoo() {}
// emitter.on("foo", onFoo); // 订阅
// emitter.off("foo", onFoo); // 取消订阅事件
